import 'dart:async';
import 'dart:convert';

import 'package:common_utils/common_utils.dart';
import 'package:crypto/crypto.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:part_time_job_pro/common/index.dart';

///工具类
class CommonUtil {
  ///将Color转为MaterialColor
  static MaterialColor createMaterialColor(Color color) {
    List strengths = <double>[.05];
    Map<int, Color> swatch = {};
    final int r = color.red, g = color.green, b = color.blue;

    for (int i = 1; i < 10; i++) {
      strengths.add(0.1 * i);
    }
    for (var strength in strengths) {
      final double ds = 0.5 - strength;
      swatch[(strength * 1000).round()] = Color.fromRGBO(
        r + ((ds < 0 ? r : (255 - r)) * ds).round(),
        g + ((ds < 0 ? g : (255 - g)) * ds).round(),
        b + ((ds < 0 ? b : (255 - b)) * ds).round(),
        1,
      );
    }
    return MaterialColor(color.value, swatch);
  }

  ///判断空
  static bool isEmpty(var val) {
    return (val == null || val == '' || val == 'null') ? true : false;
  }

  ///是否不是空字符串
  static bool isNotEmpty(String str) {
    return !isEmpty(str) ? true : false;
  }

  ///判断集合为空
  static bool isEmptyList(List list) {
    return list.isEmpty ? true : false;
  }

  ///处理空值
  static dynamic fuckEmpty(var val) {
    return val != null ? json.encode(val) : null;
  }

  /// md5 加密
  static String generateMd5(String data) {
    var content = const Utf8Encoder().convert(data);
    var digest = md5.convert(content);
    LogUtil.e("md5====>${digest.toString}");
    return digest.toString();
  }

  /// Base64加密
  static String encodeBase64(String data) {
    var content = utf8.encode(data);
    var digest = base64Encode(content);
    return digest;
  }

  ///Base64解密
  static String decodeBase64(String data) {
    return String.fromCharCodes(base64Decode(data));
  }

  ///utf8转换
  static String utf8convert(String text) {
    List<int> bytes = text.toString().codeUnits;
    return utf8.decode(bytes);
  }

  ///格式化手机号为344
  static String formatMobile344(String mobile) {
    if (isEmpty(mobile)) return '';
    mobile =
        mobile.replaceAllMapped(RegExp(r"(^\d{3}|\d{4}\B)"), (Match match) {
      return '${match.group(0)} ';
    });
    if (mobile.isNotEmpty && mobile.endsWith(' ')) {
      mobile = mobile.substring(0, mobile.length - 1);
    }
    return mobile;
  }

  ///纯数字 ^[0-9]*$
  static bool pureDigitCharacters(String input) {
    const String regex = "^[0-9]*\$";
    return matches(regex, input);
  }

  ///大陆手机号码11位数，匹配格式：前三位固定格式+后8位任意数
  /// 此方法中前三位格式有：
  /// 13+任意数 * 15+除4的任意数 * 18+除1和4的任意数 * 17+除9的任意数 * 147
  static bool validPhone(String str) {
    return RegExp(
            '^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}\$')
        .hasMatch(str);
  }

  // 是否为正确的QQ号码、微信号、QQ邮箱
  // - [微信号正则校验，qq正则，邮箱正则,英文名正则](https://blog.csdn.net/qq_29091239/article/details/80075981)
  // - [微信号正则校验](https://blog.csdn.net/unknowna/article/details/50524529)
  static bool validQQ(String input) {
    const String regex = '^[1-9][0-9]{4,9}\$';
    return matches(regex, input);
  }

  ///微信号验证
  static bool validWeChatId(String input) {
    const String regex = '^[a-zA-Z]{1}[-_a-zA-Z0-9]{5,19}\$';
    return matches(regex, input);
  }

  ///邮箱账号验证
  static bool validQQMail(String input) {
    const String regex = '^[1-9][0-9]{4,9}@qq.com\$';
    return matches(regex, input);
  }

  ///验证密码 8~20位数字和字符组合
  static bool isLoginPassword(String input) {
    const String regex = '^[0-9a-zA-Z_]{8,20}\$';
    return matches(regex, input);
  }

  ///是否匹配
  static bool matches(String regex, String input) {
    if (input.isNotEmpty || input.isEmpty) return false;
    return RegExp(regex).hasMatch(input);
  }

  /// 十六进制颜色，
  /// hex, 十六进制值，例如：0xffffff,
  /// alpha, 透明度 [0.0,1.0]
  static Color hexColor(int hex, {double alpha = 1}) {
    if (alpha < 0) {
      alpha = 0;
    } else if (alpha > 1) {
      alpha = 1;
    }
    return Color.fromRGBO((hex & 0xFF0000) >> 16, (hex & 0x00FF00) >> 8,
        (hex & 0x0000FF) >> 0, alpha);
  }

  //金额格式化
  static String formatNum(targetNum, {point = 3}) {
    if (targetNum != null) {
      String str = double.parse(targetNum.toString()).toString();
      // 分开截取
      List<String> sub = str.split('.');
      // 处理值
      List val = List.from(sub[0].split(''));
      // 处理点
      List<String> points = List.from(sub[1].split(''));
      //处理分割符
      for (int index = 0, i = val.length - 1; i >= 0; index++, i--) {
        // 除以三没有余数、不等于零并且不等于1 就加个逗号
        if (index % 3 == 0 && index != 0 && i != 1) val[i] = val[i] + ',';
      }
      // 处理小数点
      for (int i = 0; i <= point - points.length; i++) {
        points.add('0');
      }
      //如果大于长度就截取
      if (points.length > point) {
        // 截取数组
        points = points.sublist(0, point);
      }
      // 判断是否有长度
      if (points.isNotEmpty && point > 0) {
        return '${val.join('')}.${points.join('')}';
      } else {
        return val.join('');
      }
    } else {
      return "0.00";
    }
  }

  //字符串转数值
  static double fmtNumber(dynamic num) {
    double formatNum = num;
    LogUtil.e(
        "formatNum=====$formatNum  formatNum===>${formatNum.toStringAsFixed(3)}");
    return double.parse(formatNum.toStringAsFixed(2));
  }

  //获取缓存token信息
  static String getLoginToken() {
    String? token = StorageService.to.getString(STORAGE_USER_TOKEN_KEY);
    LogUtil.e("缓存中获取到的token信息：$token");
    return token;
  }

  //设置缓存token信息
  static setLoginToken(String token) async {
    StorageService.to.setString(STORAGE_USER_TOKEN_KEY, token).then((value) {
      LogUtil.e("设置token缓存成功：$token");
    });
  }

  //获取缓存用户信息
  static LoginUser getLoginUser() {
    String? loginUser = StorageService.to.getString(STORAGE_USER_PROFILE_KEY);
    LogUtil.e("缓存中获取到的用户信息：$loginUser");
    return jsonDecode(loginUser);
  }

  //设置缓存用户信息
  static setLoginUser(user) async {
    StorageService.to
        .setString(STORAGE_USER_PROFILE_KEY, jsonEncode(user))
        .then((value) {
      LogUtil.e("设置用户缓存成功：$user");
    });
  }

  //是否登录
  static bool isLogined() {
    String? token = StorageService.to.getString(STORAGE_USER_TOKEN_KEY);
    bool isLogined = CommonUtil.isNotEmpty(token);
    LogUtil.e("用户是否登录:$isLogined");
    return isLogined;
  }

  //清楚token信息
  static clearLoginInfo() async {
    await StorageService.to.remove(STORAGE_USER_TOKEN_KEY);
    await StorageService.to.remove(STORAGE_USER_PROFILE_KEY);
  }

  //debounce 避免高频率事件
  static Function debounce(Function fn, [int t = 30]) {
    late Timer debounce;
    return () {
      // 还在时间之内，抛弃上一次
      if (debounce.isActive) {
        LogUtil.e("请勿重复点击！");
        debounce.cancel();
      }
      debounce = Timer(Duration(milliseconds: t), () {
        fn();
      });
    };
  }

  ///判断是不是视频
  static bool isVideoFile(String preffix) {
    bool isVideo = false;
    if (preffix.contains("mp4") ||
        preffix.contains("avi") ||
        preffix.contains("mov")) {
      isVideo = true;
    }
    return isVideo;
  }

  ///判断是不是图片
  static bool isImageFile(String preffix) {
    bool isImage = false;
    if (preffix.contains("jpg") ||
        preffix.contains("jpge") ||
        preffix.contains("png") ||
        preffix.contains("gif") ||
        preffix.contains("webp") ||
        preffix.contains("bmp")) {
      isImage = true;
    }
    return isImage;
  }

  //清除焦点
  static clearFocus() {
    // 使用下面的方式，会触发不必要的build。
    // FocusScope.of(context).unfocus();
    FocusManager.instance.primaryFocus?.unfocus();
  }

  //获取焦点
  static requestFocus(BuildContext context, FocusNode node) {
    FocusScope.of(context).requestFocus(node);
  }

  //刷新组件
  static Header getClassicHeader({required String refreshedText}) {
    return ClassicHeader(
      triggerOffset: 70,
      dragText: "下拉刷新",
      armedText: "松开手刷新",
      readyText: "数据刷新中",
      processingText: "刷新中...",
      processedText: refreshedText,
      failedText: "刷新失败",
      noMoreText: "~暂无新数据~",
      messageText: "最后更新: 今天 %T",
    );
  }

  //加载更多组件
  static Footer getClassicalFooter({required String loadedText}) {
    return ClassicFooter(
      triggerOffset: 60,
      dragText: "下拉刷新",
      readyText: "松开手刷新",
      processingText: "刷新中...",
      processedText: loadedText,
      failedText: "刷新失败",
      noMoreText: "~暂无新数据~",
      messageText: "最后更新: 今天 %T",
    );
  }
}
